/*!
\copyright  Copyright (c) 2025 Qualcomm Technologies International, Ltd.
            All Rights Reserved.
            Qualcomm Technologies International, Ltd. Confidential and Proprietary.
\file
\ingroup    user_eq
\brief      Kymera implementation of User EQ operation API

*/

#include "user_eq_operation.h"
#include "user_eq_ctx.h"
#include "user_eq_callback_handlers.h"
#include "user_eq_set_params.h"
#include "kymera_music_processing.h"
#include <logging.h>
#include <message.h>
#include <panic.h>
#include <stdlib.h>

#define USER_EQ_OPERATION_INTERNAL_USER_EQ_APPLY_GAINS 0

static void userEq_MusicProcessingStart(void);
static void userEq_MusicProcessingStop(void);

static void userEq_OperationMessageHandler(Task task, MessageId id, Message message);
static uint8 getUcidForBank(uint8 bank);

kymera_music_processing_event_callbacks_t music_processing_callbacks = {
    .MusicProcessingStart = userEq_MusicProcessingStart,
    .MusicProcessingStop = userEq_MusicProcessingStop,
};

static TaskData task_data = {.handler = userEq_OperationMessageHandler};

uint32 eq_gain_apply_delay = 50;

void UserEq_OperationInit(void)
{
    Kymera_RegisterMusicProcessingCallbacks(&music_processing_callbacks);
}

bool UserEq_IsPresent(void)
{
    return Kymera_IsMusicProcessingPresent();
}

bool UserEq_OperationIsActive(void)
{
    return ((Kymera_GetUserEqOperator()) ? (TRUE) : (FALSE));;
}

static uint8 getUcidForBank(uint8 bank)
{
    uint8 ucid = 0;

    if (bank == EQ_BANK_USER)
    {
        ucid = bank;
    }
    else if (bank < EQ_BANK_USER)
    {
        ucid = bank + 1;
    }

    return ucid;
}

bool UserEq_OperationSelectPreset(uint8 preset)
{
    uint8 bank = preset;
    DEBUG_LOG_VERBOSE("Kymera_SelectEqBankNow %d", bank);

    if(Kymera_IsMusicProcessingPresent() && bank <= EQ_BANK_USER)
    {
        const Operator peq_op = Kymera_GetUserEqOperator();

        DEBUG_LOG_VERBOSE("Kymera_SelectEqBankNow selecting %d", bank);

        if(peq_op)
        {
            OperatorsStandardSetUCID(peq_op, getUcidForBank(bank));

            if(bank == EQ_BANK_USER)
            {
                MessageSendLater((Task)&task_data, USER_EQ_OPERATION_INTERNAL_USER_EQ_APPLY_GAINS, NULL, eq_gain_apply_delay);
            }
        }

        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

bool UserEq_OperationSetGains(uint8 start_band, uint8 end_band, int16 *gains)
{
    UNUSED(gains);

    return UserEq_OperationApplyGains(start_band, end_band);
}

void UserEq_OperationApplyCurrentPresetAndGains(void)
{
    UserEq_OperationSelectPreset(UserEq_CtxGet()->eq.selected_eq_bank);
}

bool UserEq_OperationApplyGains(uint8 start_band, uint8 end_band)
{
    bool user_eq_bands_set = FALSE;
    const Operator peq_op = Kymera_GetUserEqOperator();


    DEBUG_LOG_VERBOSE("UserEq_OperationApplyGains start %d, end %d, peq_op 0x%x\n", start_band, end_band, peq_op);

    if (peq_op)
    {
        set_params_data_t* set_params_data = UserEq_SetParamsCreateWithGains(start_band, end_band, UserEq_CtxGet()->gains);
        OperatorsStandardSetParameters(peq_op, set_params_data);
        free(set_params_data);

        user_eq_bands_set = TRUE;
    }

    return user_eq_bands_set;
}

bool UserEq_OperationApplyAllGains(void)
{
    return UserEq_OperationApplyGains(0, UserEq_CtxGet()->eq.user.number_of_bands - 1);
}

void UserEq_OperationSetBypass(void)
{
    UserEq_OperationSelectPreset(0);
}

static void userEq_MusicProcessingStart(void)
{
    UserEq_HandleActivityIndication(TRUE);
}

static void userEq_MusicProcessingStop(void)
{
    UserEq_HandleActivityIndication(FALSE);
}

static void userEq_OperationMessageHandler(Task task, MessageId id, Message message)
{
    UNUSED(task);
    UNUSED(message);

    switch(id)
    {
        case USER_EQ_OPERATION_INTERNAL_USER_EQ_APPLY_GAINS:
        {
            if(UserEq_CtxGet()->eq.selected_eq_bank == EQ_BANK_USER)
            {
                UserEq_OperationApplyAllGains();
            }
        }
        break;

        default:
        break;
    }
}
